Amazon ECSハンズオンで構築したRuby on RailsアプリをCI/CD経由でデプロイしてみた
Amazon ECSで管理しているアプリのCI/CD環境を整えたい
おのやんです。
Amazon ECS(以下、ECS)で管理しているアプリのCI/CD環境を整えたいと思ったことはありませんか?私はあります。
AWSでは、比較的簡単な構成を自差しに触りながら構築して、AWSサービスを学べるハンズオンがあります。今回私がECSを学習する上でも、こちらの日本語ハンズオンを参考にしました。このハンズオンでは、Ruby on Rails(以下、Rails)アプリケーションをコンテナ化してECSで管理したのち、発展内容としてAWSのCodeシリーズを使ったCI/CD環境を整備していきます。
RailsアプリをECSで管理するまでの内容は、こちらの記事でまとめていますので、今回の内容はこちらの記事に続けて書く形にないます。
ということで、今回はハンズオンの内容を進める形で、具体的な構成図とともに、CI/CD環境の整備をまとめていきたいと思います。
目指す構成
今回目指す構成はこちらになります。右側のECS環境は、さきほど共有した別記事にてまとめています。今回は左側のAWS CodePipeline(以下、CodePipeline)を作成していき、その中でAWS CodeCommit(以下、CodeCommit)を用いたソースコード管理やAWS CodeBuild(以下、CodeBuild)を用いたコンテナイメージのビルド、AWS CodeDeploy(以下、CodeDeploy)を用いたアプリケーションのデプロイを設定してきます。
ビルド設定ファイルの設定
ここからの流れでは、基本的にハンズオンの流れに従っていきます。また補足情報なども適宜付け加えながらまとてめていきます。
今回のハンズオンでは、AWS CLIを使ってCodeCommitのリポジトリを作成します。
Cloud9環境のコンソールで以下のコマンドを実行して、CodeCommitリポジトリを作成してきます。
$ aws codecommit create-repository --repository-name rails-app
正常に実行されると、このように CodeCommit上でリポジトリを確認できるようになります。
続いて、このCodeCommitリポジトリをCloud9環境の~/environment/handsonディレクトリと連携します。
cd ~/environment/handson git init -b main git remote add origin codecommit::ap-northeast-1://rails-app
これらGit関係の設定ができましたら、CodeBuildでビルドするための設定ファイルを作成します。ハンズオンの流れで、Cloud9環境に~/environment/handson/
のディレクトリが作成されていると思いますので、この直下にbuildspec.yaml
とimagedefinitions.json
を作成します。なおハンズオンにはimagedefinitions.json
のサンプルコードは掲載されていませんので、いい感じに作成します。
version: 0.2 env: variables: CONTAINER_NAME: "rails-app" phases: pre_build: commands: # AWS アカウント ID を取得する - AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text) # リポジトリの URI を設定する - REPOSITORY_URI=${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/${CONTAINER_NAME} # コミット ID をもとに、コンテナイメージのタグを生成する - IMAGE_TAG=$(echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} | cut -c 1-7) # ECR にログインする - aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com build: commands: # コンテナイメージをビルドする - docker build -t ${REPOSITORY_URI}:latest . # 生成したイメージタグを付与する - docker tag ${REPOSITORY_URI}:latest ${REPOSITORY_URI}:${IMAGE_TAG} post_build: commands: # ビルドしたコンテナイメージを ECR にプッシュする - docker push ${REPOSITORY_URI}:${IMAGE_TAG} # "コンテナの名前" と "コンテナイメージの URI" を imagedefinitions.json に書き込む - printf '[{"name":"%s","imageUri":"%s"}]' ${CONTAINER_NAME} ${REPOSITORY_URI}:${IMAGE_TAG} > imagedefinitions.json artifacts: files: - imagedefinitions.json
[ { "name": "rails-app", "imageUri": "<account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/rails-app:latest" } ]
これらのファイルを作成したら、 Cloud9環境でGitを設定して、~/environment/handson/
直下のファイルをCodeCommitにプッシュします。
git add . git commit -m "Initial commit" git push origin main
正常にプッシュできると、こちらの用にCodeCommitで各ファイルを管理できるようになります。
Codeipelineでパイプラインの作成
続いて、Ci/CDで用いるパイプラインを作成していきます。具体的には、CodePipelineを作成する段階でCodeBuild、CodeDeployの設定をまとめて行うイメージです。
その中でも、まずはCodePipelineのパイプラインを作成していきます。
CodePipelineのコンソール画面に入り、「パイプラインを作成する」ボタンを押下します。
パイプライン名はecs-test-pipeline
とします。またハンズオンの内容にはありませんが、ハンズオン作成時からアップデートが入り、パイプラインタイプ・実行モードの項目がパイプライン設定画面に追加されています。パイプラインタイプはV2、実行モードはキュー(パイプラインタイプV2が必須)を選択します。サービスロールは「新しいサービスロール」を選択します。こちらを選択することで、ロール名にもある通りAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipeline
というIAMロールが自動で作成・適用されます。
CodePipelineのV1とV2は、基本構造が同じであり、V2を選択することで追加のパラメータを設定することができます。今回はハンズオンの内容に影響はありませんので、できることが多いV2を選択していて問題ありません。
またAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipeline
ロールにはAWSCodePipelineServiceRole-ap-northeast-1-ecs-handson-pipeline
ポリシーがアタッチされており、その内容は以下のようになっています。CodeシリーズやEC2, ECS, ALBなど、さまざまなリソースにアクセスできるようCodePipelineに許可を与えています。
続いて、ソースとなるコードを追加します。ソースプロバイダは「AWS CodeCommit」、リポジトリ名は「rails-app」、ブランチ名は「main」を選択します。
続いて、ビルドに関する設定を行っていきます。構成図でいうと、CodeCommit内のコード変更を検知して、コンテナイメージをビルドする部分です
プロバイダーは「AWS CodeBuild」で、リージョンは「アジアパシフィック(東京)」を選択します。ここから、プロジェクト名の「プロジェクトを作成する」を押下します。
すると、Webブラウザの別ウィンドウが開き、ビルドプロジェクトの設定画面が表示されます。ここから、ビルドに関する詳細な設定を進めていきます。なお、ここはハンズオン作成当時からコンソール画面が大幅に変わっていますので、注意してください。
まず、ビルドプロジェクトの名前はecs-test-project
にしておきます。
続いて、ビルドを実行する環境について設定を進めていきます。それぞれの項目について、「オンデマンド」「マネージド型イメージ」「ECS」を選択していきます。また、オペレーティングシステムはAmazon Linux、ランタイムは「Standard」、イメージは「aws/codebuild/amazonlinux2-x86_64-standard:5.0」、イメージのバージョンは最近のイメージを使用するよう設定します。またサービスロールについては「新しいサービスロール」を選択し、新規でIAMロールが作成されるようにします。
そしてここの「追加設定」トグルを開き、特権付与の部分にチェックを入れます。
続いて、Buildspecに関する設定です。さきほどbuildspec.yaml
を作成していますので、「buildspec.yaml
ファイルを使用する」を選択し、buildspec.yaml
のファイル名を入力しておきます。
ログについては、CloudWatch Logsにチェックを入れておきます。
こちらを設定し終わったら、「CodePipelineに進む」を押下します。すると、こちらのウィンドウが自動的に閉じて、ビルドステージ設定画面に戻ります。「プロジェクト名」をみてみると、ecs-test-projectが追加されているのがわかります。
最後にデプロイに関する設定を行います。構成図でいうと、ECRからコンテナイメージを取得してECS管理のFargateにデプロイする部分です。
それぞれの項目について、デプロイプロバイダーは「Amazon ECS」、「リージョンはアジアパシフィク」、クラスターはecs-test-cluster、サービスはecs-test-fargate-service、イメージ定義ファイルはimagedefinitions.jsonを選択します。
以上を入力できたら、パイプラインを作成します。なお、このままではIAMロールに必要な権限が足りない状態ですので、ビルドに失敗します。ですので、CodeBuildのビルドプロジェクトを設定した時に作成されたcodebuild-ecs-test-project-service-role
に、田 AmazonEC2 ContainerRegistryFullAccess
のマネージドポリシーを追加しておきます。
これで、再度ビルドを実行すると、今回は問題なく通ることが確認できます
コードの変更をパイプライン経由で反映・デプロイ
それでは、ハンズオンにならって実際にコードを変更し、デプロイしていきたいと思います。Cloud9上でDockerfile
を以下のように編集します。
# ruby:3.2.1 というベースイメージを取得する FROM public.ecr.aws/docker/library/ruby:3.2.1 # 必要なパッケージ群を取得する RUN apt-get update -qq && \ apt-get install -y nodejs postgresql-client npm && \ rm -rf /var/lib/apt/lists/\* # ローカルにあるファイルをコンテナイメージ内にコピーする WORKDIR /myapp COPY Gemfile /myapp/Gemfile # Rails アプリケーションを作成する RUN bundle install && \ rails new . -O && \ sed -i -e "52a\ config.hosts.clear\n config.web_console.allowed_ips = '0.0.0.0/0'\n config.action_dispatch.default_headers.delete('X-Frame-Options')" config/environments/development.rb # welcome ページの背景色を blue にする RUN sed -i -e "s/background-color: #F0E7E9;/background-color: #99CCFF;/g" /usr/local/bundle/gems/railties-7.0.4/lib/rails/templates/rails/welcome/index.html.erb # Rails を 3000 番ポートで起動する EXPOSE 3000 CMD ["rails", "server", "-b", "0.0.0.0", "-p", "3000"]
こちらの変更をcommitし、CodeCommitにプッシュします。
$ git add Dockerfile $ git commit -m "Change background color" $ git push origin main
すると、CodeCommitのプッシュをEvent Bridgeで検知して、CodePipelineが開始します。CodeCommitのソースコードを元にCodeBuildでコンテナイメージが作成され、このイメージを元にECS管理のFargate上にデプロイされます。
Fargate用のALBのドメインにアクセスすると、Railsの背景色が青色になったことを確認できました。
CodePipelineのパイプラインの中で、ビルドやデプロイなどを設定する
AWSのマネジメントコンソールを操作して、実際にCodeシリーズを設定することで、それぞれのサービスがどのように動作するのかを理解することができました。
ハンズオンと実際のコンソールで多少の違いはありましたが、AWSサービスを用いたCI/CDを学べる資料としても、ECSハンズオンは非常に効果的だと感じました。みなさんもぜひECSハンズオンをやってみてください。では!